package cn.yeziji.jwt;

import com.alibaba.fastjson.JSONArray;
import io.jsonwebtoken.Claims;
import io.jsonwebtoken.Jwts;
import io.jsonwebtoken.SignatureAlgorithm;
import org.springframework.security.core.authority.SimpleGrantedAuthority;

import java.text.ParseException;
import java.text.SimpleDateFormat;
import java.util.*;

/**
 * Jwt 工具类
 *
 * @author gzkemays
 */
public class JwtUtils {
  private String subject = "yezijigroup-subject";
  private String secret = "yezijigroup-secret";
  private String header = "token";
  private String prefix = "Bearer";
  private String roleClams = "roles";
  private long expired = 1000 * 24 * 60 * 60 * 7;

  private interface Builder {
    /**
     * 初始化参数
     *
     * @param params 参数
     * @return JwtUtils
     */
    JwtUtils init(String... params);
  }

  private JwtUtils() {}

  private JwtUtils(JwtUtilBuilder builder) {
    subject = builder.subject;
    secret = builder.secret;
    header = builder.header;
    prefix = builder.prefix;
    roleClams = builder.roleClams;
    expired = builder.expired;
  }

  public static class JwtUtilBuilder implements Builder {
    private String subject = "yeizjigroup-subject";
    private String secret = "yeizjigroup-secret";
    private String header = "token";
    private String prefix = "Bearer";
    private String roleClams = "roles";
    private long expired = 1000 * 24 * 60 * 60 * 7;

    private JwtUtilBuilder() {}

    @Override
    public JwtUtils init(String... params) {
      for (int i = 0; i < params.length; i++) {
        switch (i) {
          case 1:
            this.secret = Optional.of(params[1]).orElse("yezijigroup-secret");
            break;
          case 2:
            this.header = Optional.of(params[2]).orElse("token");
            break;
          case 3:
            this.prefix = Optional.of(params[3]).orElse("Bearer");
            break;
          case 4:
            this.roleClams = Optional.of(params[4]).orElse("roles");
            break;
          case 5:
            this.expired =
                Optional.of(Long.parseLong(params[5])).orElse((long) 1000 * 24 * 60 * 60 * 7);
            break;
          default:
            this.subject = Optional.of(params[0]).orElse("yezijigroup-subject");
        }
      }
      return new JwtUtils(this);
    }
  }

  public static JwtUtilBuilder settings() {
    return new JwtUtilBuilder();
  }

  public <T> String generateJsonWebToken(Object authorities, Object id, Object username) {
    return Jwts.builder()
        .setSubject(subject)
        .claim(roleClams, authorities)
        .claim("id", id)
        .claim("username", username)
        .setIssuedAt(new Date())
        .setExpiration(new Date(System.currentTimeMillis() + expired))
        .signWith(SignatureAlgorithm.HS256, secret)
        .compact();
  }

  /**
   * 生成token
   *
   * @param username 用户名
   * @param role 角色定位
   * @return token
   */
  public String createToken(String username, String role) {
    Map<String, Object> map = new HashMap<>(1);
    map.put(roleClams, role);
    return Jwts.builder()
        .setSubject(username)
        .setClaims(map)
        .claim("username", username)
        .setIssuedAt(new Date())
        .setExpiration(new Date(System.currentTimeMillis() + expired))
        .signWith(SignatureAlgorithm.HS256, secret)
        .compact();
  }

  /**
   * 检测 jwt
   *
   * @param token token信息
   * @return 声明信息
   */
  public Claims checkJwt(String token) {
    try {
      return Jwts.parser().setSigningKey(secret).parseClaimsJws(token).getBody();
    } catch (Exception e) {
      e.printStackTrace();
      return null;
    }
  }

  /**
   * 获取用户名
   *
   * @param token token 信息
   * @return 用户名【插入 claims 之中】
   */
  public String getUsername(String token) {
    Claims claims = Jwts.parser().setSigningKey(secret).parseClaimsJws(token).getBody();
    return claims.get("username").toString();
  }

  /**
   * 获取用户角色
   *
   * @param token token 信息
   * @return 用户角色定位
   */
  @SuppressWarnings("all")
  public List<SimpleGrantedAuthority> getUserRole(String token) {
    Claims claims = Jwts.parser().setSigningKey(secret).parseClaimsJws(token).getBody();
    List roles = (List) claims.get(roleClams);
    String json = JSONArray.toJSONString(roles);
    List<SimpleGrantedAuthority> grantedAuthorityList =
        JSONArray.parseArray(json, SimpleGrantedAuthority.class);
    return grantedAuthorityList;
  }

  /**
   * 是否过期
   *
   * @param token token信息
   * @return 判断 expire 是否过期
   */
  public boolean isExpiration(String token) {
    Claims claims = Jwts.parser().setSigningKey(secret).parseClaimsJws(token).getBody();
    return claims.getExpiration().before(new Date());
  }

  public static void main(String[] args) throws ParseException {
    Date date = new Date();
    String day = date.toString();
    SimpleDateFormat dateFormat = new SimpleDateFormat("yyyy-MM-dd");
    String format = dateFormat.format(date);

    SimpleDateFormat dateFormat1 =
        new SimpleDateFormat("EEE MMM d HH:mm:ss 'CST' yyyy", Locale.ENGLISH);
    Date parse = dateFormat1.parse(day);
  }
}
